"""
消息模块 - 实现通信消息的基本属性和方法
"""

import time
import uuid
import config

class Message:
    """基础消息类"""
    
    def __init__(self, sender_id, receiver_id, msg_type, content=None, priority=None):
        """
        初始化消息实例
        
        参数:
            sender_id: 发送方无人机ID
            receiver_id: 接收方无人机ID (可以是None表示广播消息)
            msg_type: 消息类型，如'EMERGENCY', 'CONTROL'等
            content: 消息内容
            priority: 消息优先级 (如果为None，则根据消息类型自动设置)
        """
        self.id = str(uuid.uuid4())[:8]  # 生成唯一消息ID
        self.sender_id = sender_id
        self.receiver_id = receiver_id
        self.type = msg_type
        self.content = content if content is not None else {}
        
        # 时间属性
        self.creation_time = time.time()
        self.sent_time = None
        self.received_time = None
        
        # 从配置中获取消息类型属性
        type_config = config.MESSAGE_TYPES.get(msg_type, {})
        
        # 设置优先级 (0最高)
        self.priority = priority if priority is not None else type_config.get('priority', 4)
        
        # 设置消息大小 (字节)
        self.size = type_config.get('size', 512)
        
        # 设置消息截止时间 (毫秒)
        self.deadline = type_config.get('deadline', 500)
        
        # 重传相关
        self.retries = 0
        self.max_retries = config.MAX_RETRIES
        self.acknowledged = False
        
        # 传输相关
        self.delivery_path = []  # 消息传递路径
        self.hops = 0  # 经过的跳数
        
    def mark_sent(self):
        """标记消息为已发送"""
        self.sent_time = time.time()
        
    def mark_received(self):
        """标记消息为已接收"""
        self.received_time = time.time()
        
    def mark_acknowledged(self):
        """标记消息为已确认"""
        self.acknowledged = True
        
    def increment_retry(self):
        """增加重试次数"""
        self.retries += 1
        return self.retries <= self.max_retries
        
    def add_hop(self, uav_id):
        """添加跳数和路径记录"""
        self.delivery_path.append(uav_id)
        self.hops += 1
        
    def is_expired(self, current_time=None):
        """
        检查消息是否过期
        
        参数:
            current_time: 当前时间，如果为None则使用系统当前时间
            
        返回:
            布尔值，表示消息是否过期
        """
        if current_time is None:
            current_time = time.time()
            
        # 如果已发送但未收到确认
        if self.sent_time is not None:
            elapsed_ms = (current_time - self.sent_time) * 1000  # 转换为毫秒
            return elapsed_ms > self.deadline
        
        return False
    
    def get_delay(self):
        """
        获取消息传输延迟(毫秒)
        
        返回:
            延迟时间(毫秒)，如果消息未完成传输则返回None
        """
        if self.sent_time is not None and self.received_time is not None:
            return (self.received_time - self.sent_time) * 1000  # 转换为毫秒
        return None
    
    def __str__(self):
        """字符串表示"""
        return f"Message-{self.id} [{self.type}] from {self.sender_id} to {self.receiver_id} (priority: {self.priority})"


class AcknowledgementMessage(Message):
    """确认消息类"""
    
    def __init__(self, original_message, sender_id):
        """
        初始化确认消息
        
        参数:
            original_message: 原始消息
            sender_id: 发送确认的无人机ID
        """
        super().__init__(
            sender_id=sender_id,
            receiver_id=original_message.sender_id,
            msg_type='ACK',
            content={'original_message_id': original_message.id},
            priority=original_message.priority  # 保持与原消息相同的优先级
        )
        # 确认消息通常较小
        self.size = 64
        # 确认消息通常有较短的截止时间
        self.deadline = min(100, original_message.deadline / 2)


class EmergencyMessage(Message):
    """紧急消息类"""
    
    def __init__(self, sender_id, receiver_id=None, content=None):
        """
        初始化紧急消息
        
        参数:
            sender_id: 发送方无人机ID
            receiver_id: 接收方无人机ID (None表示广播)
            content: 消息内容
        """
        super().__init__(
            sender_id=sender_id,
            receiver_id=receiver_id,
            msg_type='EMERGENCY',
            content=content,
            priority=0  # 最高优先级
        )
        # 紧急消息可以有更多的重试次数
        self.max_retries = config.MAX_RETRIES * 2 